#include "TCPClient.h"
#include <string.h>
#define TCPBUFFER 13

TCPClient::TCPClient()
{
	m_Socket = -1;
	m_bConnect = false;
}

TCPClient::~TCPClient()
{
	closeTcpSocket();
}

bool TCPClient::connectToServer(const char *serverIP,int serPort,int nTimeOut)
{
	do
	{
		if(!serverIP || serPort<=0 || serPort>65525 || (0==strcmp("0.0.0.0",serverIP))|| nTimeOut<0 )
		{
			printf("Error:TCP serverIP or port is error!\n");
			m_bConnect= false;
			break;
		}
		if((m_Socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		{
#ifdef TCPCLIENT_DEBUG
			printf("Error: TCP socket init failed....\n");
#endif
			m_bConnect=false;
			break;
		}
		struct sockaddr_in destaddr;
		memset((void *)&destaddr,0,sizeof(destaddr)); 
		destaddr.sin_family=AF_INET;
		destaddr.sin_port=htons(serPort);
		destaddr.sin_addr.s_addr=inet_addr(serverIP); 
        
#ifdef TCPCLIENT_DEBUG
		printf("connecting to %s:%d\n",serverIP,serPort);
#endif
		//set timeout
#ifdef _WIN32
		int nTvlen=nTimeOut;
#else
		struct timeval nTvlen={nTimeOut/1000,(nTimeOut%1000)*1000}; //windows is int
#endif

		int retOpt=setsockopt(m_Socket,SOL_SOCKET,SO_SNDTIMEO,(const char*)&nTvlen,sizeof(nTvlen));
		if(0 != retOpt)
		{
			fprintf(stderr, "setsockopt ::failed, %s\n", strerror(errno));
		}

		int nConnRet=connect(m_Socket,(struct sockaddr*)&destaddr,sizeof(destaddr));
		if(-1==nConnRet)
		{
#ifdef TCPCLIENT_DEBUG
			printf("Error: connect failed!\n");
#endif
			m_bConnect= false;
			break;
		}
		m_bConnect=true;
	}while(false);
	return m_bConnect;
}


int TCPClient::sendData(const unsigned char *data,int nLength,int nTimeOut)
{
	int nSend = 0;
	do
	{
		if(!data||nLength<=0||nTimeOut<0)
		{
#ifdef TCPCLIENT_DEBUG
			printf("Error: !data||nLength<=0||nTimeOut<0\n");
#endif
			nSend= -1;
			break;
		}

		if(!m_bConnect)
		{
#ifdef TCPCLIENT_DEBUG
			printf("Error: Havent connect yet! m_bConnect==false\n");
#endif
			nSend= -1;
			break;
		}

#ifdef _WIN32
		int tvOut=nTimeOut;
#else
		struct timeval tvOut;
		tvOut.tv_sec = nTimeOut/1000;   
		tvOut.tv_usec = (nTimeOut%1000)*1000;
#endif
		int retSet=setsockopt(m_Socket,SOL_SOCKET,SO_SNDTIMEO,(const char*)&tvOut,sizeof(tvOut)); 
		if(0 !=retSet)
		{
			printf("Error: setSocketOpt failed:%s\n",strerror(errno));
		}
		nSend=send(m_Socket,data,nLength,0);
		if (nSend == -1)
		{
			printf("Error: TCP Send Failed!\n");
			break;
		}
	}while(false);
	return nSend;
}

int TCPClient::receive(unsigned char *data, int nBufLength, int nTimeOut)
{
	int nRecv = 0;
	do
	{
		if(!data||nBufLength<=0||nTimeOut<0)
		{
			printf("Error: !data||nBufLength<=0||nTimeOut<0\n");
			nRecv= -1;
			break;
		}
		if(!m_bConnect)
		{
			printf("Error: TCP Receive Failed,Not Connected.\n");
			m_bConnect=true;
			nRecv=-1;
			break;
		}
#ifdef _WIN32
		int tvOut=nTimeOut;
#else
		struct timeval tvOut;
		tvOut.tv_sec = nTimeOut/1000;
		tvOut.tv_usec = (nTimeOut%1000)*1000;
#endif
		int retSet=setsockopt(m_Socket, SOL_SOCKET,SO_RCVTIMEO,(const char*)&tvOut,sizeof(tvOut)); 
		if(0 !=retSet)
		{
			printf("Error: setSocketOpt failed:%s\n",strerror(errno));
		}
		nRecv = recv(m_Socket, data,nBufLength,0);
	}while(false);
	return nRecv;
}

int TCPClient::receiveAllData(unsigned char *bufRecv,int nTimeOut)
{
	int nTotal=0;
	unsigned char recv_buff[TCPBUFFER+1] = { 0 };
	int	 nCount=0;

	do
	{
		memset(recv_buff,0,sizeof(char)*(TCPBUFFER+1));
		nCount=receive(recv_buff, sizeof(char)*TCPBUFFER, nTimeOut);
		if(nCount>0)
		{
			memcpy(bufRecv+nTotal,recv_buff,sizeof(recv_buff));
			nTotal+=nCount;
		}
	}while(nCount>0);
	return nTotal;
}

void TCPClient::closeTcpSocket()
{
	if(m_bConnect)
	{
#ifdef _WIN32
		closesocket(m_Socket);
#else
		close(m_Socket);
#endif
		m_bConnect = false;
	}
}
